/*
 * Copyright (C) 2008 Universidade Federal de Campina Grande
 *  
 * This file is part of OurGrid. 
 *
 * OurGrid is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free 
 * Software Foundation, either version 3 of the License, or (at your option) 
 * any later version. 
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT 
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
 * for more details. 
 * 
 * You should have received a copy of the GNU Lesser General Public License 
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 * 
 */
package org.ourgrid.peer.ui.async.gui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.table.TableColumnModel;

import org.glite.jdl.JobAd;
import org.ourgrid.common.interfaces.to.WorkerInfo;
import org.ourgrid.gridMonitor.operations.PeerLocalOperation;
import org.ourgrid.peer.ui.async.client.PeerAsyncInitializer;

/**
 * It represents a panel where it is possible to view the status of the workers.
 */
public class WorkerTablePanel extends javax.swing.JPanel {

	private static final long serialVersionUID = 1L;
	
	/** Creates new form WorkerTablePanel */
    public WorkerTablePanel() {
    	initComponents();
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        tableScrollPane = new javax.swing.JScrollPane();
        workerTable = new javax.swing.JTable();

        workerTable.setModel(getTableModel());
        workerTable.addMouseListener(new MouseAdapter() {
        	@Override
        	public void mouseClicked(MouseEvent e) {
        		if (workerTable.getSelectedColumn() == WorkerTableModel.DELETE_COLUMN) {
        			deleteTableRow(workerTable.getSelectedRow());
        		}else{
        			updateTextArea(workerTable.getSelectedRow());
        		}
        	}
        });
        
        workerTable.setAutoResizeMode( JTable.AUTO_RESIZE_ALL_COLUMNS );
        tableScrollPane.setViewportView(workerTable);
        
        Dimension size = workerTable.getPreferredSize();
        TableColumnModel columnModel = workerTable.getColumnModel();
        columnModel.getColumn( 0 ).setPreferredWidth( (int)(size.width * 0.20) );
        columnModel.getColumn( 1 ).setPreferredWidth( (int)(size.width * 0.75) );
        columnModel.getColumn( 2 ).setPreferredWidth( (int)(size.width * 0.05) );
        
        BorderLayout bLayout = new BorderLayout();
        this.setLayout(bLayout);
        add(tableScrollPane, BorderLayout.CENTER);
        
    }// </editor-fold>//GEN-END:initComponents
    
    protected void updateTextArea(int selectedRow) {
    	if(selectedRow == -1){
    		propertiesArea.setText("Click on a worker for information");
    	}else{
    		WorkerInfo workerInfo = getTableModel().getWorkerInfo(selectedRow);
    		String expression = workerInfo.getWorkerSpec().getExpression();
    		if(expression != null){
    			try {
    				propertiesArea.setText( new JobAd( expression ).toString( true, true ) );
    			} catch ( Exception e ) {
    				propertiesArea.setText( "Error parsing JobAd: " + e.getMessage() );
    			}
    		}else{
    			propertiesArea.setText( formatMap( workerInfo.getWorkerSpec().getAttributes() ) );
    		}
    	}
	}
    
	/**
	 * Format a map of properties to a single {@link String}.
	 * @param map
	 * @return
	 */
	private String formatMap( Map<String,String> map ) {
		StringBuilder sb = new StringBuilder("[\n");
		Set<Entry<String,String>> entrySet = map.entrySet();
		for ( Entry<String,String> entry : entrySet ) {
			sb.append( "\t" + entry.getKey() + ": " + entry.getValue() + "\n" );
		}
		return sb.append( "]\n" ).toString();
	}


	/**
     * Removes the specified row of this table.
     * @param selectedRow The row to be removed.
     */
    private void deleteTableRow(int selectedRow) {
    	
    	WorkerInfo workerInfo = getTableModel().getWorkerInfo(selectedRow);
    	
    	int confirmDeletion = JOptionPane.showConfirmDialog(null, "Delete worker [" + workerInfo.getId() + "] ?", 
    			"Delete worker", JOptionPane.YES_NO_OPTION);
    	
    	if (confirmDeletion == JOptionPane.YES_OPTION) {
    		
    		PeerAsyncInitializer.getInstance().getComponentClient().removeWorker(workerInfo.getWorkerSpec());
    	}
    	updateTextArea( -1 );
	}

	/**
     * Returns the table that displays the status of the worker.
     * @return The table that displays the status of the worker.
     */
    private WorkerTableModel getTableModel() {
    	if (model == null) {
    		model = new WorkerTableModel(new LinkedList<WorkerInfo>());
    	}
    	return model;
    }
    
    /**
     * Defines the informations about the workers.
     * @param data The informations about the workers.
     */
    public void setTableModelData(Collection<WorkerInfo> data) {
    	getTableModel().setData(data);
    	getTableModel().fireTableDataChanged();
    	if (!data.isEmpty())
    		PeerLocalOperation.sendPeerWorkerInformation(data);
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JScrollPane tableScrollPane;
    private javax.swing.JTable workerTable;
    // End of variables declaration//GEN-END:variables
    
    private WorkerTableModel model;
	private JTextArea propertiesArea;

	/**
	 * 
	 */
	public void peerStopped() {
		setTableModelData(Collections.<WorkerInfo>emptyList());
		updateTextArea( -1 );
	}

	/**
	 * @param propertiesArea
	 */
	public void setTextArea( JTextArea propertiesArea ) {
		this.propertiesArea = propertiesArea;
	}

}
